package GtEngine

import (
	"net"
	"time"
	. "tksLog"
	. "tksStatic"
	. "tksTcp"
	. "tksUint"
)

type ServerInfo struct {
	TimeoutCount int
	Conn         net.Conn
	t            *time.Ticker
	Toc          chan int
}

var CmdServers map[uint32]*ServerInfo //CmdServers[cmd]=ServerInfo
var IdServers map[uint32]*ServerInfo  //IdServers[serverid]=ServerInfo
var ConnServers map[string]*ServerInfo

func init() {
	CmdServers = make(map[uint32]*ServerInfo)
	IdServers = make(map[uint32]*ServerInfo)
	ConnServers = make(map[string]*ServerInfo)
}

//

func (s *ServerInfo) run() {
	for {
		select {
		case c := <-s.Toc:
			s.TimeoutCount = c
		case <-s.t.C:
			if s.TimeoutCount > 3 {
				return
			} else if s.TimeoutCount >= 0 {
				s.TimeoutCount = s.TimeoutCount + 1
			} else {
				break
			}
		}
	}
}

//

func sendRsp(conn net.Conn, cmd uint32, from uint32, to uint32, ret Ret) {
	var rsp ServerConnectGateRsp
	rsp.R = ret
	data, _ := MsgToBuf(rsp)
	Debug("send rsp, cmd: %d, data: %s", cmd, string(data))
	SendBuffer(conn, cmd, from, to, data)
}

func registerServer(serverid uint32, cmds []interface{}, conn net.Conn) *ServerInfo {
	info := new(ServerInfo)
	info.Conn = conn
	info.TimeoutCount = 0
	info.Toc = make(chan int, 1)
	info.t = time.NewTicker(5 * time.Second)
	// id大于0，为游戏服务器id
	// 0为gate的统一ID
	// id小于0，为公用服务器，例如聊天服务器，跨服战斗服务器
	if serverid < 0 {
		for _, cmd := range cmds {
			CmdServers[cmd.(uint32)] = info
		}

	}
	IdServers[serverid] = info
	return info
}

func FindServerById(serverid uint32) *ServerInfo {
	info, ok := IdServers[serverid]
	if ok {
		return info
	} else {
		return nil
	}
}

func FindServerByCmd(cmd uint32) *ServerInfo {
	info, ok := CmdServers[cmd]
	if ok {
		return info
	} else {
		return nil
	}
}

func FindServerByAddr(addr string) *ServerInfo {
	info, ok := ConnServers[addr]
	if ok {
		return info
	} else {
		return nil
	}
}

func ServerConnect(conn net.Conn, from uint32, to uint32, buf []byte) {
	Debug("recv server connset from %s %u, info: %s", conn.RemoteAddr().String(), from, string(buf))
	json, err := BufToMsg(buf)
	if err != nil {
		sendRsp(conn, CmdServerConnectGateRsp, to, from, RetMsgFormatError)
		return
	}
	id, _ := json.Get("Id").Int()
	cmds, _ := json.Get("Cmds").Array()
	info := FindServerById(uint32(id))
	if info == nil {
		info = registerServer(uint32(id), cmds, conn)
		ConnServers[conn.RemoteAddr().String()] = info
		go info.run()
	} else {
		delete(ConnServers, info.Conn.RemoteAddr().String())
		ConnServers[conn.RemoteAddr().String()] = info
		//
		info.TimeoutCount = 0
		info.Conn = conn
	}
	sendRsp(conn, CmdServerConnectGateRsp, to, from, RetSucc)
}
